﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Random = System.Random;

namespace HotelManagementClient.Utlis
{
    public static class DoorLockEncryption
    {
        /// <summary>
        /// 数据亦或加解密
        /// </summary>
        /// <param name="hexContent"></param>
        /// <param name="hexKey"></param>
        /// <returns></returns>
        public static  string EncryptDecryptToHex(string hexContent, string hexKey)
        {
            byte[] contentBytes = ConverUtil.ToHexByteArray(hexContent.Trim());

            byte[] keyBytes = ConverUtil.ToHexByteArray(hexKey.Trim());

            for (int i = 0; i < contentBytes.Length; i++)
            {
                contentBytes[i] = (byte)(contentBytes[i] ^ keyBytes[i % keyBytes.Length]);
            }

            return BitConverter.ToString(contentBytes).Replace("-", "");
        }

        /// <summary>
        /// 数据加密
        /// </summary>
        /// <param name="content">加密内容</param>
        /// <param name="key">加密密钥</param>
        /// <returns></returns>
        public static string encryptedHex(string content,string key)
        {
            content = content.Replace(" ","");
            //判断校验数据是否正确

            //除去原始校验值的长度
            int removeTailLen = content.Length - 2;
            //计算出来的校验值
            string calculateCheckStr= CalculateChecksum(content.Substring(0,removeTailLen));
            //原始校验值
            string contentCheck = content.Substring(removeTailLen);

            if (calculateCheckStr.Equals(contentCheck))
            {
                //四级异或后的数据
                string level4Key = content.Substring(22, 12);
                string level4Data = content.Substring(36, content.Length-36-2);
                string level4EncryptData = EncryptDecryptToHex(level4Data, level4Key);
                string level4NewData = content.Substring(0, 36) + level4EncryptData + contentCheck;
                WriteLog.Write(0, DateUtil.NowF() + " 四级==>密钥:" + level4Key + ",待加密内容:" + level4Data + ",加密后的内容:" + level4EncryptData + ",新组成的四级数据:" + level4NewData);

                //三级异或后的数据
                string level3Key = content.Substring(14, 8);
                string level3Data = level4NewData.Substring(22, level4NewData.Length-22-2);
                string level3EncryptData = EncryptDecryptToHex(level3Data, level3Key);
                string level3NewData = content.Substring(0, 22) + level3EncryptData + contentCheck;
                WriteLog.Write(0, DateUtil.NowF() + " 三级==>密钥:" + level3Key + ",待加密内容:" + level3Data + ",加密后的内容:" + level3EncryptData + ",新组成的三级数据:" + level3NewData);

                //二级异或后的数据
                string level2Key = content.Substring(6, 8);
                string level2Data = level3NewData.Substring(14, level3NewData.Length-14-2);
                string level2EncryptData = EncryptDecryptToHex(level2Data, level2Key);
                string level2NewData = content.Substring(0, 14) + level2EncryptData + contentCheck;
                WriteLog.Write(0, DateUtil.NowF() + " 二级==>密钥:" + level2Key + ",待加密内容:" + level2Data + ",加密后的内容:" + level2EncryptData + ",新组成的二级数据:" + level2NewData);

                //一级异或后的数据
                string level1Key = key;
                string level1Data = level2NewData.Substring(6, level2NewData.Length-6-2);
                string level1EncryptData = EncryptDecryptToHex(level1Data, level1Key);
                string level1NewData = content.Substring(0, 6) + level1EncryptData + contentCheck;
                string level1NewData1 = content.Substring(0, 6) + level1EncryptData;
                WriteLog.Write(0, DateUtil.NowF() + " 一级==>密钥:" + level1Key + ",待加密内容:" + level1Data + ",加密后的内容:" + level1EncryptData + ",新组成的一级数据:" + level1NewData);
                string newCalculate = CalculateChecksum(level1NewData1);
                level1NewData1 += newCalculate;
                WriteLog.Write(0, DateUtil.NowF() + " 最终数据包:" + level1NewData1 );
                // 加密后的数据
                return level1NewData1;
            }
            else
            {
                WriteLog.Write(1, "加密失败,错误的数据:" + content);
            }
            return "";
        }

        /// <summary>
        /// 数据解密
        /// </summary>
        /// <param name="content">解密内容</param>
        /// <param name="key">解密密钥</param>
        /// <returns></returns>
        public static string decryptedContent(string content,string key)
        {
            content = content.Replace(" ", "");
            List<string> resultList = new List<string>();
            int count = CountOccurrences(content, "A1");
            while (true)
            {
                if (count > 0)
                {
                    //10
                    int index = content.IndexOf("A1");
                    if (index != -1)
                    {
                        //0000
                        string lenHex = content.Substring(index + 2, 4);
                        //数据长度 18
                        int dataLen = Convert.ToInt32(lenHex, 16);
                        // 38
                        int countLen = (19 + dataLen) * 2;
                        if (content.Length >= countLen+2)
                        {
                            string newContent = content.Substring(index, countLen);
                            //计算的累加校验
                            string calculateStr = CalculateChecksum(newContent);
                            //获取的累加校验值
                            string calculateCotent = content.Substring(index + countLen, 2);

                            if (calculateStr.Equals(calculateCotent))
                            {
                                resultList.Add(newContent + calculateCotent);
                                content = content.Substring(index + countLen + 2);
                                count = CountOccurrences(content, "A1");
                            }
                            else
                            {
                                content = content.Substring(index + 2);
                            }
                        }
                        else
                        {
                            break;
                        }
                        
                    }

                }
                else
                {
                    break;
                }
                
            }
            string result = "";
            resultList.ForEach(res =>
            {
                //除去原始校验值的长度
                int removeTailLen = res.Length - 2;
                //计算出来的校验值
                string calculateCheckStr = CalculateChecksum(res.Substring(0, removeTailLen));
                //原始校验值
                string contentCheck = res.Substring(removeTailLen);

                if (calculateCheckStr.Equals(contentCheck))
                {
                    //一级异或后的数据
                    string level1Key = key;
                    string level1Data = res.Substring(6, res.Length - 6 - 2);
                    string level1EncryptData = EncryptDecryptToHex(level1Data, level1Key);
                    string level1NewData = res.Substring(0, 6) + level1EncryptData + contentCheck;
                    WriteLog.Write(0, DateUtil.NowF() + " 一级==>密钥:" + level1Key + ",待解密内容:" + level1Data + ",解密后的内容:" + level1EncryptData + ",新组成的一级数据:" + level1NewData);

                    //二级异或后的数据
                    string level2Key = level1NewData.Substring(6, 8);
                    string level2Data = level1NewData.Substring(14, level1NewData.Length - 14 - 2);
                    string level2EncryptData = EncryptDecryptToHex(level2Data, level2Key);
                    string level2NewData = level1NewData.Substring(0, 14) + level2EncryptData + contentCheck;
                    WriteLog.Write(0, DateUtil.NowF() + " 二级==>密钥:" + level2Key + ",待解密内容:" + level2Data + ",解密后的内容:" + level2EncryptData + ",新组成的二级数据:" + level2NewData);

                    //三级异或后的数据
                    string level3Key = level2NewData.Substring(14, 8);
                    string level3Data = level2NewData.Substring(22, level2NewData.Length - 22 - 2);
                    string level3EncryptData = EncryptDecryptToHex(level3Data, level3Key);
                    string level3NewData = level2NewData.Substring(0, 22) + level3EncryptData + contentCheck;
                    WriteLog.Write(0, DateUtil.NowF() + " 三级==>密钥:" + level3Key + ",待解密内容:" + level3Data + ",解密后的内容:" + level3EncryptData + ",新组成的三级数据:" + level3NewData);

                    //四级异或后的数据
                    string level4Key = level3NewData.Substring(22, 12);
                    string level4Data = level3NewData.Substring(36, level3NewData.Length - 36 - 2);
                    string level4EncryptData = EncryptDecryptToHex(level4Data, level4Key);
                    string level4NewData = level3NewData.Substring(0, 36) + level4EncryptData + contentCheck;
                    string level4ResultData = level3NewData.Substring(0, 36) + level4EncryptData;
                    WriteLog.Write(0, DateUtil.NowF() + " 四级==>密钥:" + level4Key + ",待解密内容:" + level4Data + ",解密后的内容:" + level4EncryptData + ",新组成的四级数据:" + level4NewData);
                    string newCalculate = CalculateChecksum(level4ResultData);
                    level4ResultData += newCalculate;
                    WriteLog.Write(0, DateUtil.NowF() + " 最终数据包:" + level4ResultData);
                    // 解密后的数据
                    result += level4ResultData;
                }
                else
                {
                    WriteLog.Write(1, "解密失败,错误的数据:" + res);
                }
            });
            
            return result;
        }

        /// <summary>
        /// 查找字符串出现的次数
        /// </summary>
        /// <param name="input"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static int CountOccurrences(string input, string target)
        {
            int count = 0;
            int index = 0;
            while ((index = input.IndexOf(target, index)) != -1)
            {
                index += target.Length;
                count++;
            }
            return count;
        }


        /// <summary>
        /// 累加校验
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static string CalculateChecksum(string hexString)
        {
            int length = hexString.Length;
            if (length % 2 != 0)
            {
                // 十六进制字符串必须是偶数长度
                throw new ArgumentException("无效的十六进制字符串长度");
            }

            byte checksum = 0;
            for (int i = 0; i < length; i += 2)
            {
                string hexByte = hexString.Substring(i, 2);
                byte value = Convert.ToByte(hexByte, 16);
                checksum += value; // 累加每个字节
            }
            return checksum.ToString("X2");
        }




        /// <summary>
        /// 字符串转16进制字符
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string ConvertStringToHex(string input)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(input);
            return BitConverter.ToString(bytes).Replace("-", "");
        }


        /// <summary>
        /// 生成指定字节数的随机数并返回十六进制字符
        /// </summary>
        /// <param name="byteLen"></param>
        /// <returns></returns>
        public static string GenRandomForHexNum(int byteLen)
        {
            byte[] randomBytes = new byte[byteLen];
            Random random = new Random();
            random.NextBytes(randomBytes);

            int randomNumber = BitConverter.ToInt32(randomBytes, 0);
            return randomNumber.ToString("X");
        }

        /// <summary>
        /// 时间戳的十六进制字符串
        /// </summary>
        /// <param name="timestamp"></param>
        /// <returns></returns>
        public static string TimeStmpHex(long timestamp)
        {
            // 将时间戳转换为byte数组
            byte[] timestampBytes = BitConverter.GetBytes(timestamp);

            // 如果需要将时间戳转换为4字节的十六进制字符串，可以按照需要截取字节数组，并使用ToString方法将其转换为十六进制字符串
            return  BitConverter.ToString(timestampBytes, 0, 4).Replace("-", "");
        }


        /// <summary>
        /// 组装数据
        /// </summary>
        /// <param name="equipmentCode">设备编码</param>
        /// <param name="protocolVersion">协议版本</param>
        /// <param name="command">命令</param>
        /// <param name="dataStr">数据</param>
        /// <returns></returns>
        public static string AssemblyData(string equipmentCode,string protocolVersion,string command,string dataStr)
        {
            if (string.IsNullOrEmpty(equipmentCode))
            {
                equipmentCode = "FFFFFFFFFFFF";
            }

            if (string.IsNullOrEmpty(protocolVersion))
            {
                protocolVersion = "FE";
            }
            if (string.IsNullOrEmpty(command))
            {
                command = "1A";
            }

            //数据长度
            string dataLen = "0000";
            if (!string.IsNullOrEmpty(dataStr))
            {
                dataStr = dataStr.Trim();
                int dataStrLen = dataStr.Length / 2;
                dataLen = ConvertStringToHex(dataStrLen.ToString("X4"));
            }
            //随机数
            string ramdomStr = GenRandomForHexNum(4);
            //时间戳
            string timeStmpStr = TimeStmpHex(DateUtil.NowDataTimeStamp());
            //头1  长度2 随机数4 时间戳4 设备编码6 协议版本1 命令1 数据N  校验1
            string resultStr = "A1" + dataLen + ramdomStr + timeStmpStr + equipmentCode + protocolVersion + command + dataStr;
            string calculateStr =CalculateChecksum(resultStr);
            return resultStr+=calculateStr;
        }
    }
}
